const http = require('http')
const os = require('os')
const { URL } = require('url')
global.api = require('./http.api')
const zlib = require('zlib')
const { pipeline } = require('stream')

global.sysInfo = (arr = ['pid', 'arch', 'cpu', 'avg', 'mem', 'uptime', 'home']) => {
  const arrFn = {
    pid() { return process.pid },
    arch() { return os.arch() },
    cpu() { return process.cpuUsage() },
    avg() {
      const avg = []
      os.loadavg().map(v => { avg.push(parseFloat(v.toFixed(2))) })
      return avg
    },
    mem() { return Object.assign({ free: os.freemem(), total: os.totalmem() }, process.memoryUsage()) },
    uptime() { return process.uptime() },
    home() { return process.env.HOME || process.env.USERPROFILE.replace(/\\/g, '/') || '../' },
    network() { return os.networkInterfaces() },
    cpus() { return os.cpus() },
    version() { return process.version },
    os() { return { uptime: os.uptime(), arch: os.arch(), type: os.type(), release: os.release(), platform: os.platform(), hostname: os.hostname(), homedir: os.homedir(), EOL: os.EOL } }
  }
  const rs = {}
  arr.map(v => { rs[v] = arrFn[v]() })
  return rs
}

module.exports = () => {
  const proxy = http.createServer({ allowHalfOpen: true })
  const requestCall = async(req, res) => {
    const socket = req.socket
    socket.host = req.headers.host.split(':')[0].trim()
    socket.method = req.method
    req.ip = socket.remoteAddress
    req.host = socket.host
    if (req.ip.includes(':')) req.ip = req.ip.split(':').pop()
    if (req.headers['x-real-ip']) req.ip = req.headers['x-real-ip']
    const url = new URL('http://' + req.headers.host + req.url)
    const get = {}
    let gi = 0
    url.searchParams.forEach((v, k) => {
      let isArr = false
      let objArr
      k = k.replace(/\[\]/g, `[${gi}]`)
      gi++
      if (k.includes('][')) { // 解析对象
        k = k.replace(/\[/g, '.').replace(/\]/g, '')
        Acan.objSet(get, k, v)
        const objArr = (o) => {
          const arr = []
          Acan.each(o, (v, k) => { arr.push(v) })
          return arr
        }
        const objChk = (o) => {
          Acan.each(o, (v, k) => {
            if (Acan.isStr(v)) return
            if (/^\d+$/.test(Object.keys(v))) {
              o[k] = objArr(v)
            } else {
              objChk(v)
            }
          })
        }
        objChk(get)
      } else {
        get[k] = v
      }
      // Adebug.log(get)
    })
    req.data = async() => {
      return await new Promise(r => {
        const arr = []
        req.on('data', (data) => { arr.push(data) })
        req.on('end', (data) => {
          r(JSON.parse(Buffer.concat(arr).toString()))
        })
      }) || {}
    }
    const onError = (err) => {
      if (err) {
        res.end()
        console.error('发生错误:', err)
      }
    }
    const acceptEncoding = req.headers['accept-encoding'] || ''
    res.zip = (raw) => {
      if (!conf.gzip) return res.end(raw)
      // if (raw.length < 512) return pipeline(raw, res, onError)
      if (/\bdeflate\b/.test(acceptEncoding)) {
        res.setHeader('Content-Encoding', 'deflate')
        pipeline(raw, zlib.createDeflate(), res, onError)
      } else if (/\bgzip\b/.test(acceptEncoding)) {
        res.setHeader('Content-Encoding', 'gzip')
        pipeline(raw, zlib.createGzip(), res, onError)
      } else if (/\bbr\b/.test(acceptEncoding)) {
        res.setHeader('Content-Encoding', 'br')
        pipeline(raw, zlib.createBrotliCompress(), res, onError)
      } else {
        pipeline(raw, res, onError)
      }
    }
    res.json = (rs) => {
      res.setHeader('Server', 'Anat/2.0')
      res.setHeader('Access-Control-Allow-Origin', '*')
      res.setHeader('Content-Type', 'application/json')
      res.zip(JSON.stringify(rs)); // res.destroy()
    }
    res.text = (rs) => {
      res.setHeader('Server', 'Anat/2.0')
      res.setHeader('Content-Type', 'text/html; charset=UTF-8')
      res.zip(rs); // res.destroy()
    }
    res.html = (rs) => {
      const html = `<!doctype html><html><head><meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"><meta charset="utf-8" /></head>
<body style="padding: 1rem;text-align:center;">
<div>${rs}</div>
</body></html>
`
      res.setHeader('Server', 'Anat/2.0')
      res.setHeader('Content-Type', 'text/html; charset=UTF-8')
      res.zip(html); // res.destroy()
    }
    let act = url.pathname.substr(1) || 'index'
    if (act === 'favicon.ico') return res.end()
    if (act.includes('/')) {
      const arr = act.split('/')
      if (arr.length === 2) req.ns = arr[0], act = arr[1]
    }
    const fn = api[act]
    if (!fn) return Adebug.log('no api act', act)
    fn(get, req, res, proxy, (rs = {}) => { res.json(rs) })
  }
  proxy.on('request', requestCall)
  // const connectCall = async(req, res) => {}
  // proxy.on('connection', connectCall)
  proxy.maxConnections = Infinity
  proxy.setTimeout(5000)
  proxy.on('connection', function(socket) {
    socket.setKeepAlive(true)
    // console.log("A new connection", socket.remotePort)
    socket.setTimeout(10000)
  }).listen(conf.port, conf.ip, () => { Adebug.log(`http listen ok`) })
  global.proxy = proxy
  return proxy
}